home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / os2 / elvis172.zip / move2.c < prev    next >
C/C++ Source or Header  |  1993-01-06  |  6KB  |  305 lines

  1. /* move2.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This function contains the movement functions that perform RE searching */
  12.  
  13. #include "config.h"
  14. #include "vi.h"
  15. #include "regexp.h"
  16.  
  17. extern long    atol();
  18.  
  19. static regexp    *re;    /* compiled version of the pattern to search for */
  20. static        prevsf;    /* boolean: previous search direction was forward? */
  21.  
  22. #ifndef NO_EXTENSIONS
  23. /*ARGSUSED*/
  24. MARK m_wsrch(word, m, cnt)
  25.     char    *word;    /* the word to search for */
  26.     MARK    m;    /* the starting point */
  27.     int    cnt;    /* ignored */
  28. {
  29.     char    buffer[30];
  30.  
  31.     /* wrap \< and \> around the word */
  32.     strcpy(buffer, "/\\<");
  33.     strcat(buffer, word);
  34.     strcat(buffer, "\\>");
  35.  
  36.     /* show the searched-for word on the bottom line */
  37.     move(LINES - 1, 0);
  38.     qaddstr(buffer);
  39.     clrtoeol();
  40.     refresh();
  41.  
  42.     /* search for the word */
  43.     return m_fsrch(m, buffer);
  44. }
  45. #endif
  46.  
  47. MARK    m_nsrch(m, cnt, cmd)
  48.     MARK    m;    /* where to start searching */
  49.     long    cnt;    /* number of searches to do */
  50.     int    cmd;    /* command character -- 'n' or 'N' */
  51. {
  52.     int    oldprevsf; /* original value of prevsf, so we can fix any changes */
  53.  
  54.     DEFAULT(1L);
  55.  
  56.     /* clear the bottom line.  In particular, we want to loose any
  57.      * "(wrapped)" notice.
  58.      */
  59.     move(LINES - 1, 0);
  60.     clrtoeol();
  61.  
  62.     /* if 'N' command, then invert the "prevsf" variable */
  63.     oldprevsf = prevsf;
  64.     if (cmd == 'N')
  65.     {
  66.         prevsf = !prevsf;
  67.     }
  68.  
  69.     /* search forward if prevsf -- i.e., if previous search was forward */
  70.     while (--cnt >= 0L && m != MARK_UNSET)
  71.     {
  72.         if (prevsf)
  73.         {
  74.             m = m_fsrch(m, (char *)0);
  75.         }
  76.         else
  77.         {
  78.             m = m_bsrch(m, (char *)0);
  79.         }
  80.     }
  81.  
  82.     /* restore the old value of prevsf -- if cmd=='N' then it was inverted,
  83.      * and the m_fsrch() and m_bsrch() functions force it to a (possibly
  84.      * incorrect) value.  The value of prevsf isn't supposed to be changed
  85.      * at all here!
  86.      */
  87.     prevsf = oldprevsf;
  88.     return m;
  89. }
  90.  
  91.  
  92. MARK    m_fsrch(m, ptrn)
  93.     MARK    m;    /* where to start searching */
  94.     char    *ptrn;    /* pattern to search for */
  95. {
  96.     long    l;    /* line# of line to be searched */
  97.     char    *line;    /* text of line to be searched */
  98.     int    wrapped;/* boolean: has our search wrapped yet? */
  99.     int    pos;    /* where we are in the line */
  100. #ifndef CRUNCH
  101.     long    delta = INFINITY;/* line offset, for things like "/foo/+1" */
  102. #endif
  103.  
  104.     /* remember: "previous search was forward" */
  105.     prevsf = TRUE;
  106.  
  107.     if (ptrn && *ptrn)
  108.     {
  109.         /* locate the closing '/', if any */
  110.         line = parseptrn(ptrn);
  111. #ifndef CRUNCH
  112.         if (*line)
  113.         {
  114.             delta = atol(line);
  115.         }
  116. #endif
  117.         ptrn++;
  118.  
  119.         /* free the previous pattern */
  120.         if (re) _free_(re);
  121.  
  122.         /* compile the pattern */
  123.         re = regcomp(ptrn);
  124.         if (!re)
  125.         {
  126.             return MARK_UNSET;
  127.         }
  128.     }
  129.     else if (!re)
  130.     {
  131.         msg("No previous expression");
  132.         return MARK_UNSET;
  133.     }
  134.  
  135.     /* search forward for the pattern */
  136.     pos = markidx(m) + 1;
  137.     pfetch(markline(m));
  138.     if (pos >= plen)
  139.     {
  140.         pos = 0;
  141.         m = (m | (BLKSIZE - 1)) + 1;
  142.     }
  143.     wrapped = FALSE;
  144.     for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
  145.     {
  146.         /* wrap search */
  147.         if (l > nlines)
  148.         {
  149.             /* if we wrapped once already, then the search failed */
  150.             if (wrapped)
  151.             {
  152.                 break;
  153.             }
  154.  
  155.             /* else maybe we should wrap now? */
  156.             if (*o_wrapscan)
  157.             {
  158.                 l = 0;
  159.                 wrapped = TRUE;
  160.                 continue;
  161.             }
  162.             else
  163.             {
  164.                 break;
  165.             }
  166.         }
  167.  
  168.         /* get this line */
  169.         line = fetchline(l);
  170.  
  171.         /* check this line */
  172.         if (regexec(re, &line[pos], (pos == 0)))
  173.         {
  174.             /* match! */
  175.             if (wrapped && *o_warn)
  176.                 msg("(wrapped)");
  177. #ifndef CRUNCH
  178.             if (delta != INFINITY)
  179.             {
  180.                 l += delta;
  181.                 if (l < 1 || l > nlines)
  182.                 {
  183.                     msg("search offset too big");
  184.                     return MARK_UNSET;
  185.                 }
  186.                 force_flags = LNMD|INCL;
  187.                 return MARK_AT_LINE(l);
  188.             }
  189. #endif
  190.             return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
  191.         }
  192.         pos = 0;
  193.     }
  194.  
  195.     /* not found */
  196.     msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
  197.     return MARK_UNSET;
  198. }
  199.  
  200. MARK    m_bsrch(m, ptrn)
  201.     MARK    m;    /* where to start searching */
  202.     char    *ptrn;    /* pattern to search for */
  203. {
  204.     long    l;    /* line# of line to be searched */
  205.     char    *line;    /* text of line to be searched */
  206.     int    wrapped;/* boolean: has our search wrapped yet? */
  207.     int    pos;    /* last acceptable idx for a match on this line */
  208.     int    last;    /* remembered idx of the last acceptable match on this line */
  209.     int    try;    /* an idx at which we strat searching for another match */
  210. #ifndef CRUNCH
  211.     long    delta = INFINITY;/* line offset, for things like "/foo/+1" */
  212. #endif
  213.  
  214.     /* remember: "previous search was not forward" */
  215.     prevsf = FALSE;
  216.  
  217.     if (ptrn && *ptrn)
  218.     {
  219.         /* locate the closing '?', if any */
  220.         line = parseptrn(ptrn);
  221. #ifndef CRUNCH
  222.         if (*line)
  223.         {
  224.             delta = atol(line);
  225.         }
  226. #endif
  227.         ptrn++;
  228.  
  229.         /* free the previous pattern, if any */
  230.         if (re) _free_(re);
  231.  
  232.         /* compile the pattern */
  233.         re = regcomp(ptrn);
  234.         if (!re)
  235.         {
  236.             return MARK_UNSET;
  237.         }
  238.     }
  239.     else if (!re)
  240.     {
  241.         msg("No previous expression");
  242.         return MARK_UNSET;
  243.     }
  244.  
  245.     /* search backward for the pattern */
  246.     pos = markidx(m);
  247.     wrapped = FALSE;
  248.     for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
  249.     {
  250.         /* wrap search */
  251.         if (l < 1)
  252.         {
  253.             if (*o_wrapscan)
  254.             {
  255.                 l = nlines + 1;
  256.                 wrapped = TRUE;
  257.                 continue;
  258.             }
  259.             else
  260.             {
  261.                 break;
  262.             }
  263.         }
  264.  
  265.         /* get this line */
  266.         line = fetchline(l);
  267.  
  268.         /* check this line */
  269.         if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
  270.         {
  271.             /* match!  now find the last acceptable one in this line */
  272.             do
  273.             {
  274.                 last = (int)(re->startp[0] - line);
  275.                 try = (int)(re->endp[0] - line);
  276.             } while (try > 0
  277.                  && regexec(re, &line[try], FALSE)
  278.                  && (int)(re->startp[0] - line) < pos);
  279.  
  280.             if (wrapped && *o_warn)
  281.                 msg("(wrapped)");
  282. #ifndef CRUNCH
  283.             if (delta != INFINITY)
  284.             {
  285.                 l += delta;
  286.                 if (l < 1 || l > nlines)
  287.                 {
  288.                     msg("search offset too big");
  289.                     return MARK_UNSET;
  290.                 }
  291.                 force_flags = LNMD|INCL;
  292.                 return MARK_AT_LINE(l);
  293.             }
  294. #endif
  295.             return MARK_AT_LINE(l) + last;
  296.         }
  297.         pos = BLKSIZE;
  298.     }
  299.  
  300.     /* not found */
  301.     msg(*o_wrapscan ? "Not found" : "Hit top without finding RE");
  302.     return MARK_UNSET;
  303. }
  304.  
  305.